<template>
  <t-card :bordered="false">
    <!-- 自定义搜索 -->
    <custom-search ref="customSearchRef" v-slot="{ params }" @submit="handleInitTable">
      <t-col :span="3">
        <t-form-item label="菜单名称" name="name">
          <t-input v-model:value="params.name" clearable placeholder="" />
        </t-form-item>
      </t-col>
      <t-col :span="3">
        <t-form-item label="状态" name="status">
          <t-select
            v-model:value="params.status"
            :options="dictionaryStore.get('common_status')"
            clearable
            filterable
            placeholder=""
          />
        </t-form-item>
      </t-col>
    </custom-search>
    <!-- 自定义表格 -->
    <custom-table
      ref="customTableRef"
      row-key="id"
      :columns="columns"
      :api="menuCRUD.list"
      column-controller-key="menuList"
      :on-before-set-data="handleTableSetData"
      :tree="{ expandTreeNodeOnClick: true }"
    >
      <template #topContent>
        <div style="margin-bottom: var(--td-comp-margin-xxl)">
          <t-button
            v-permission="['system:menu:create']"
            @click="handleOpenDialog('create', { status: 0, visible: true, keepAlive: true })"
          >
            新建菜单
          </t-button>
        </div>
      </template>
      <template #name="{ row }"> {{ row.type === 3 ? '【权限】' : '' }}{{ row.name }} </template>
      <template #icon="{ row }">
        <t-icon :name="row.icon" />
      </template>
      <template #status="{ row }">
        <t-switch
          v-model:value="row.status"
          :custom-value="[0, 1]"
          :loading="row.loading"
          @change="handleChangeStatus(row)"
        />
      </template>
      <template #operation="{ row }">
        <t-space break-line>
          <t-link
            v-permission="['system:menu:create']"
            theme="primary"
            @click.stop="handleOpenDialog('create', { parentId: row.id, status: 0, visible: true, keepAlive: true })"
          >
            新建子菜单
          </t-link>
          <t-link
            v-permission="['system:menu:query']"
            theme="primary"
            @click.stop="handleOpenDialog('read', { id: row.id })"
          >
            详情
          </t-link>
          <t-link
            v-permission="['system:menu:update']"
            theme="primary"
            @click.stop="handleOpenDialog('update', { id: row.id })"
          >
            编辑
          </t-link>
          <t-popconfirm content="确认要删除该项吗？" @confirm="handleDelete({ id: row.id })">
            <t-link v-permission="['system:menu:delete']" theme="danger"> 删除 </t-link>
          </t-popconfirm>
        </t-space>
      </template>
    </custom-table>
    <!-- 自定义对话框 -->
    <custom-dialog
      ref="customDialogRef"
      v-slot="{ formData, readonly }"
      :api-map="menuCRUD"
      header="*菜单"
      @request-success="handleDialogRequestSuccess"
    >
      <t-form-item label="上级菜单" name="parentId" :rules="[{ required: true, message: '请选择上级菜单' }]">
        <t-cascader
          v-model:value="formData.parentId"
          :options="simpleMenuList"
          :keys="{ value: 'id', label: 'name' }"
          placeholder="请选择上级菜单"
          filterable
          clearable
          :readonly="readonly"
          check-strictly
        />
      </t-form-item>
      <t-form-item label="菜单名称" name="name" :rules="[{ required: true, message: '请输入菜单名称' }]">
        <t-input v-model:value="formData.name" placeholder="请输入菜单名称" clearable :readonly="readonly" />
      </t-form-item>
      <t-form-item label="菜单类型" name="type" :rules="[{ required: true, message: '请选择菜单类型' }]">
        <t-radio-group v-model:value="formData.type">
          <t-radio
            v-for="_ in dictionaryStore.get('system_menu_type', 'number')"
            :key="_.value"
            :value="_.value"
            :readonly="readonly"
          >
            {{ _.label }}
          </t-radio>
        </t-radio-group>
      </t-form-item>
      <t-form-item v-if="[1, 2].includes(formData.type)" label="菜单图标" name="icon">
        <t-select
          v-model:value="formData.icon"
          placeholder="请选择菜单图标"
          clearable
          filterable
          :readonly="readonly"
          @clear="formData.icon = null"
        >
          <t-option
            v-for="_ in manifest"
            :key="_.stem"
            :value="_.stem"
            :label="_.stem"
            style="display: inline-block; font-size: 20px"
          >
            <t-icon :name="_.stem" />
          </t-option>
          <template #prefixIcon>
            <t-icon :name="formData.icon" />
          </template>
        </t-select>
      </t-form-item>
      <t-form-item
        v-if="[1, 2].includes(formData.type)"
        label="路由路径"
        name="path"
        :rules="[{ required: true, message: '请输入路由路径' }]"
      >
        <t-input v-model:value="formData.path" placeholder="请输入路由路径" clearable :readonly="readonly" />
      </t-form-item>
      <t-form-item
        v-if="[2].includes(formData.type)"
        label="组件名称"
        name="componentName"
        :rules="[{ required: true, message: '请输入组件名称' }]"
      >
        <t-input v-model:value="formData.componentName" placeholder="请输入组件名称" clearable :readonly="readonly" />
      </t-form-item>
      <t-form-item
        v-if="[2].includes(formData.type)"
        label="组件路径"
        name="component"
        :rules="[{ required: [2].includes(formData.type), message: '请输入组件路径' }]"
      >
        <t-input v-model:value="formData.component" placeholder="请输入组件路径" clearable :readonly="readonly" />
      </t-form-item>
      <t-form-item
        v-if="[2, 3].includes(formData.type)"
        label="权限标识"
        name="permission"
        :rules="[{ required: true, message: '请输入权限标识' }]"
      >
        <t-input v-model:value="formData.permission" placeholder="请输入权限标识" clearable :readonly="readonly" />
      </t-form-item>
      <t-form-item label="显示顺序" name="sort" :rules="[{ required: true, message: '请输入显示顺序' }]">
        <t-input-number
          v-model:value="formData.sort"
          placeholder="请输入显示顺序"
          clearable
          :readonly="readonly"
          style="width: 100%"
        />
      </t-form-item>
      <t-form-item label="菜单状态" name="status" :rules="[{ required: true, message: '请选择菜单状态' }]">
        <t-radio-group v-model:value="formData.status">
          <t-radio
            v-for="_ in dictionaryStore.get('common_status', 'number')"
            :key="_.value"
            :value="_.value"
            :readonly="readonly"
          >
            {{ _.label }}
          </t-radio>
        </t-radio-group>
      </t-form-item>
      <t-form-item
        v-if="[1, 2].includes(formData.type)"
        label="显示状态"
        name="visible"
        :rules="[{ required: true, message: '请选择显示状态' }]"
      >
        <t-radio-group v-model:value="formData.visible">
          <t-radio :value="true" :readonly="readonly"> 显示 </t-radio>
          <t-radio :value="false" :readonly="readonly"> 隐藏 </t-radio>
        </t-radio-group>
      </t-form-item>
      <t-form-item
        v-if="[2].includes(formData.type)"
        label="缓存状态"
        name="keepAlive"
        :rules="[{ required: true, message: '请选择缓存状态' }]"
      >
        <t-radio-group v-model:value="formData.keepAlive">
          <t-radio :value="true" :readonly="readonly"> 缓存 </t-radio>
          <t-radio :value="false" :readonly="readonly"> 不缓存 </t-radio>
        </t-radio-group>
      </t-form-item>
    </custom-dialog>
  </t-card>
</template>

<script lang="ts">
export default {
  name: 'SystemMenu',
};
</script>

<script setup lang="ts">
import { manifest } from 'tdesign-icons-vue-next';
import { MessagePlugin, TableCol } from 'tdesign-vue-next';
import { onMounted, ref, useTemplateRef } from 'vue';

import { getSimpleMenuList, menuCRUD } from '@/api/system/menu';
import CustomDialog from '@/components/custom/dialog/index.vue';
import CustomSearch from '@/components/custom/search/index.vue';
import CustomTable from '@/components/custom/tree-table/index.vue';
import { useDictionaryStore } from '@/store';
import listToTree from '@/utils/listToTree';

// 字典仓库
const dictionaryStore = useDictionaryStore();
// 自定义搜索ref
const customSearchRef = useTemplateRef('customSearchRef');
// 自定义表格ref
const customTableRef = useTemplateRef('customTableRef');
// columns
const columns: TableCol[] = [
  { colKey: 'name', title: '菜单名称', width: 300 },
  { colKey: 'icon', title: '图标' },
  { colKey: 'sort', title: '排序' },
  { colKey: 'permission', title: '权限标识' },
  { colKey: 'componentName', title: '组件名称' },
  { colKey: 'component', title: '组件路径' },
  { colKey: 'status', title: '状态' },
  { colKey: 'operation', title: '操作', width: 250 },
];
// 处理初始化表格
const handleInitTable = () => {
  const params = { ...customSearchRef.value.params };
  customTableRef.value.initTable(params);
};
// 处理刷新表格
const handleRefreshTable = () => {
  customTableRef.value.refreshTable();
};
// 处理表格设置数据
const handleTableSetData = (data: any) => {
  return listToTree(data);
};
onMounted(() => {
  handleInitTable();
});
// 精简菜单列表
const simpleMenuList = ref([]);
// 处理获取精简菜单列表
const handleGetSimpleMenuList = () => {
  simpleMenuList.value = [];
  getSimpleMenuList()
    .then((data) => {
      simpleMenuList.value = [{ id: 0, name: '主类目', children: listToTree(data) }];
    })
    .catch(({ message }) => {
      MessagePlugin.error(message);
    });
};
// 自定义对话框ref
const customDialogRef = useTemplateRef('customDialogRef');
// 处理打开对话框
const handleOpenDialog = (mode: 'create' | 'read' | 'update', params: Record<string, any>) => {
  handleGetSimpleMenuList();
  customDialogRef.value.open(mode, params);
};
// 处理对话框请求成功
const handleDialogRequestSuccess = (result: Record<string, any>) => {
  if (result.mode === 'create') handleInitTable();
  if (result.mode === 'update') handleRefreshTable();
};
// 处理删除
const handleDelete = (params: Record<string, any>) => {
  menuCRUD
    .delete(params)
    .then(() => {
      MessagePlugin.success('删除成功');
      handleRefreshTable();
    })
    .catch(({ message }) => {
      MessagePlugin.error(message);
    });
};
// 处理改变状态
const handleChangeStatus = (row: Record<string, any>) => {
  row.loading = true;
  const params = { ...row };
  menuCRUD
    .update(params)
    .then(() => {
      MessagePlugin.success('编辑成功');
      handleRefreshTable();
    })
    .catch(({ message }) => {
      MessagePlugin.error(message);
    })
    .finally(() => {
      row.loading = false;
    });
};
</script>

<style lang="less" scoped></style>
